#include "flash.h"
#include "mrfi.h"
#include "nwk_types.h"
#include "hal_cc8051.h"
#include "ioCCxx10_bitdef.h"
#include "dma.h"


__no_init const char __code flashDataAddr[PAGE_SIZE] @ 0x7800;

void halFlashStartErase(void);
void halFlashStartWrite(void);
void halFlashStartErase();

volatile DMA_DESC dmaConfig0;

void flashWrite(uint8_t *Data, uint8_t Addr, uint16_t num)
{
  uint8_t data2[PAGE_SIZE];
  
  if((Addr+num) <= PAGE_SIZE)
  {
    DISABLE_GLOBAL_INTERRUPT;
    flashRead(data2, 0, PAGE_SIZE);
    
    for (uint8_t i = Addr; i < Addr+num; i++)
      data2[i] = *Data++;
    
    dmaConfig0.SRCADDRH  = ((uint16)data2 >> 8) & 0x00FF;
    dmaConfig0.SRCADDRL  = (uint16)data2 & 0x00FF;
    dmaConfig0.DESTADDRH = ((uint16)&X_FWDATA >> 8) & 0x00FF;
    dmaConfig0.DESTADDRL = (uint16)&X_FWDATA & 0x00FF;
    dmaConfig0.VLEN      = DMA_VLEN_USE_LEN;
    dmaConfig0.LENH      = (PAGE_SIZE >> 8) & 0x00FF;
    dmaConfig0.LENL      = PAGE_SIZE & 0x00FF;
    dmaConfig0.WORDSIZE  = DMA_WORDSIZE_BYTE;
    dmaConfig0.TMODE     = DMA_TMODE_SINGLE;
    dmaConfig0.TRIG      = DMA_TRIG_FLASH;
    dmaConfig0.SRCINC    = DMA_SRCINC_1;
    dmaConfig0.DESTINC   = DMA_DESTINC_0;
    dmaConfig0.IRQMASK   = DMA_IRQMASK_DISABLE;
    dmaConfig0.M8        = DMA_M8_USE_8_BITS;
    dmaConfig0.PRIORITY  = DMA_PRI_HIGH;
  
    /* The DMA configuration data structure may reside at any location in
     * unified memory space, and the address location is passed to the DMA
     * through DMA1CFGH:DMA1CFGL.
     */
    DMA0CFGH = ((uint16)&dmaConfig0 >> 8) & 0x00FF;
    DMA0CFGL = (uint16)&dmaConfig0 & 0x00FF;
  
    /* Waiting for the flash controller to be ready */
    while (FCTL & FCTL_BUSY);
  
    /* Configuring the flash controller. Setings:
     * FWT: 0x11 (default setting, matches 13 MHz clock frequency).
     * FADDRH:FADDRL: point to the area in flash to write to - flashDataAddr.
     */
    FWT = 0x2A;   
    FADDRH =(uint16) &flashDataAddr >> 10; //8;
    FADDRL = ((uint16)&flashDataAddr>>2 ) & 0x00FF;
  
    /* Erase the page that will be written to. */
    halFlashStartErase();
  
    /* Wait for the erase operation to complete. */
    while (FCTL & FCTL_BUSY);
  
    /* Arm the DMA channel, so that a DMA trigger will initiate DMA writing. */
    DMAARM |= DMAARM0;
  
    /* Enable flash write. Generates a DMA trigger. Must be aligned on a 2-byte
     * boundary and is therefor implemented in assembly.
     */
    halFlashStartWrite();
  
    /* Wait for DMA transfer to complete. */
    while (!(DMAIRQ & DMAIRQ_DMAIF0));
  
    /* Wait until flash controller not busy. */
    while (FCTL & (FCTL_BUSY | FCTL_SWBSY));
  
    /* By now, the transfer is completed, so the transfer count is reached.
     * The DMA channel 1 interrupt flag is then set, so we clear it here.
     */
    DMAIRQ &= ~DMAIRQ_DMAIF0;
    ENABLE_GLOBAL_INTERRUPT;
  }
}

void flashRead(uint8_t *Data, uint8_t Addr, uint8_t num)
{
  uint8_t i;
  for (i = 0; i < num; i++)
  {
      Data[i] = flashDataAddr[i+Addr];
  }
}


